package com.mybatis.boost.domain.page;


import com.mybatis.boost.domain.sort.Direction;
import com.mybatis.boost.domain.sort.Sort;
import com.mybatis.boost.domain.sort.Order;

import javax.annotation.Nullable;
import java.util.List;
import java.util.stream.Stream;

import static com.google.common.collect.Lists.newArrayList;

/**
 * @author jearton
 * @since 2017/2/17
 */
public class PageBuilder {
    private final int page;
    private int size = PageConstants.DEFAULT_PAGE_SIZE;
    private int defaultPageSize = PageConstants.DEFAULT_PAGE_SIZE;
    private int maxPageSize = PageConstants.MAX_PAGE_SIZE;
    private boolean fixEdge = PageConstants.DEFAULT_FIX_EDGE;
    private boolean pageNumberOneIndexed = PageConstants.DEFAULT_PAGE_NUMBER_ONE_INDEXED;
    private boolean queryCount = PageConstants.DEFAULT_QUERY_COUNT;
    private List<Order> orders = newArrayList();

    private PageBuilder(int page) {
        this.page = page;
    }

    public static PageBuilder page(int page) {
        return new PageBuilder(page);
    }

    public PageBuilder size(int size) {
        this.size = size;
        return this;
    }

    public PageBuilder defaultPageSize(int defaultPageSize) {
        this.defaultPageSize = defaultPageSize;
        return this;
    }

    public PageBuilder maxPageSize(int maxPageSize) {
        this.maxPageSize = maxPageSize;
        return this;
    }

    public PageBuilder fixEdge(boolean fixEdge) {
        this.fixEdge = fixEdge;
        return this;
    }

    public PageBuilder pageNumberOneIndexed(boolean pageNumberOneIndexed) {
        this.pageNumberOneIndexed = pageNumberOneIndexed;
        return this;
    }

    public PageBuilder queryCount(boolean queryCount) {
        this.queryCount = queryCount;
        return this;
    }

    public PageBuilder sort(Direction direction, String... fields) {
        Stream.of(fields).forEach(field -> orders.add(new Order(direction, field)));
        return this;
    }

    public PageBuilder sort(@Nullable Sort sort) {
        if (sort != null) {
            sort.forEach(orders::add);
        }
        return this;
    }

    public PageRequest build() {
        return new PageRequest(page, size, defaultPageSize, maxPageSize, pageNumberOneIndexed, fixEdge,
                orders.toArray(new Order[]{})).queryCount(queryCount);
    }
}
